/*
 * Copyright 2020 wangruiCoder owner
 */

package org.disk.config;

import com.alibaba.cloud.sentinel.SentinelProperties;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.config.SentinelConfig;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.redis.RedisDataSource;
import com.alibaba.csp.sentinel.datasource.redis.config.RedisConnectionConfig;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;

/**
 * 类描述
 * <p>详细描述</p>
 *
 * @author kyrie 2021/8/22 3:25 下午
 * @since jdk1.8
 */
@Component("sentinelInitConfig")
public class SentinelInitConfig implements ApplicationRunner {
    private static final Logger logger = LoggerFactory.getLogger(SentinelInitConfig.class);

    @Value("${spring.redis.host}")
    public String host;
    @Value("${spring.redis.port}")
    public int port;
    @Value("${spring.redis.password}")
    public String redisPas;

    //限流规则key前缀
    public final String RULE_FLOW = "sentinel:rule:flow:";
    public final String RULE_FLOW_CHANNEL = "sentinel_rule_flow_channel";

    //降级规则key前缀
    public final String RULE_DEGRADE = "sentinel:rule:degrade:";
    public final String RULE_DEGRADE_CHANNEL = "sentinel_rule_degrade_channel";

    //系统规则key前缀
    public final String RULE_SYSTEM = "sentinel:rule:system:";
    public final String RULE_SYSTEM_CHANNEL = "sentinel_rule_system_channel";

    @Override
    public void run(ApplicationArguments args) throws Exception {
        logger.info("init sentinel property from redis start....");
        //应用名称
        String appName = SentinelConfig.getAppName();
        //redis key 后缀

        RedisConnectionConfig config = RedisConnectionConfig.builder().withHost(host).withPort(port).withPassword(redisPas).build();

        /*
         * 装配限流配置
         */
        Converter<String, Set<GatewayFlowRule>> parser = source -> JSON.parseObject(source, new TypeReference<Set<GatewayFlowRule>>() {
        });
        ReadableDataSource<String, Set<GatewayFlowRule>> redisDataSourceFlow = new RedisDataSource<>(config, RULE_FLOW+ appName, RULE_FLOW_CHANNEL, parser);
        GatewayRuleManager.register2Property(redisDataSourceFlow.getProperty());

        if(StringUtils.isNotEmpty(redisDataSourceFlow.readSource())){
            logger.info("init gateway flow rules property success!");
        }

        /*
         * 装配降级配置
         */
        Converter<String, List<DegradeRule>> parserDegrade = source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {
        });
        ReadableDataSource<String, List<DegradeRule>> redisDataSourceDegrade = new RedisDataSource<>(config, RULE_DEGRADE+ appName, RULE_DEGRADE_CHANNEL, parserDegrade);
        DegradeRuleManager.register2Property(redisDataSourceDegrade.getProperty());

        if(StringUtils.isNotEmpty(redisDataSourceDegrade.readSource())){
            logger.info("init gateway degrade rules property success!");
        }

        /*
         * 装配系统参数
         */
        Converter<String, List<SystemRule>> parserSystem = source -> JSON.parseObject(source, new TypeReference<List<SystemRule>>() {
        });
        ReadableDataSource<String, List<SystemRule>> redisDataSourceSystem = new RedisDataSource<>(config, RULE_SYSTEM+ appName, RULE_SYSTEM_CHANNEL, parserSystem);
        SystemRuleManager.register2Property(redisDataSourceSystem.getProperty());

        if(StringUtils.isNotEmpty(redisDataSourceSystem.readSource())){
            logger.info("init gateway system rules property success!");
        }

        logger.info("init all gateway sentinel property success!");
    }
}
